using System;
using System.Collections.Generic;
using Urs.Data.Domain.Stores;
using Urs.Services.Media;

namespace Urs.Services.Stores
{
    public partial class CopyGoodsService : ICopyGoodsService
    {
        #region Fields

        private readonly IGoodsService _goodsService;
        private readonly IGoodsSpecService _goodsSpecService;
        private readonly IPictureService _pictureService;
        private readonly ICategoryService _categoryService;
        private readonly IBrandService _brandService;
        private readonly IGoodsParameterService _goodsParameterService;
        private readonly IGoodsSpecParser _goodsSpecParser;
        private readonly IGoodsTagService _goodsTagService;

        #endregion

        #region Ctor

        public CopyGoodsService(IGoodsService goodsService,
            IGoodsSpecService goodsSpecService,
            IPictureService pictureService,
            ICategoryService categoryService, IBrandService brandService,
            IGoodsParameterService goodsParameterService,
            IGoodsSpecParser goodsSpecParser, IGoodsTagService goodsTagService)
        {
            this._goodsService = goodsService;
            this._goodsSpecService = goodsSpecService;
            this._pictureService = pictureService;
            this._categoryService = categoryService;
            this._brandService = brandService;
            this._goodsParameterService = goodsParameterService;
            this._goodsSpecParser = goodsSpecParser;
            this._goodsTagService = goodsTagService;
        }

        #endregion

        #region Methods

        public virtual Goods CopyGoods(Goods goods, string newName, bool isPublished, bool copyImages)
        {
            if (goods == null)
                throw new ArgumentNullException("goods");

            if (String.IsNullOrEmpty(newName))
                throw new ArgumentException("Goods name is required");

            Goods goodsCopy = null;
            {
                goodsCopy = new Goods()
                {
                    Name = newName,
                    ShortDescription = goods.ShortDescription,
                    FullDescription = goods.FullDescription,
                    AdminComment = goods.AdminComment,
                    ShowOnHomePage = goods.ShowOnHomePage,
                    Published = isPublished,
                    Deleted = goods.Deleted,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    CategoryId = goods.CategoryId,
                    BrandId = goods.BrandId,
                    Sku = goods.Sku,
                    ManufacturerPartNumber = goods.ManufacturerPartNumber,
                    IsShipEnabled = goods.IsShipEnabled,
                    IsFreeShipping = goods.IsFreeShipping,
                    AdditionalShippingCharge = goods.AdditionalShippingCharge,
                    ManageStockEnabled = goods.ManageStockEnabled,
                    StockQuantity = goods.StockQuantity,
                    Price = goods.Price,
                    OldPrice = goods.OldPrice,
                    SpecialPrice = goods.SpecialPrice,
                    SpecialStartTime = goods.SpecialStartTime,
                    SpecialEndTime = goods.SpecialEndTime,
                    Weight = goods.Weight,
                    Length = goods.Length,
                    Width = goods.Width,
                    Height = goods.Height
                };

                _goodsService.InsertGoods(goodsCopy);

                foreach (var goodsTag in goods.GoodsTags)
                {
                    goodsCopy.GoodsTags.Add(goodsTag);
                }
                _goodsService.UpdateGoods(goods);
                foreach (var goodsTag in goods.GoodsTags)
                {
                    goodsCopy.GoodsTags.Add(new GoodsTagMapping { GoodsTag = goodsTag.GoodsTag });
                }
                _goodsService.UpdateGoods(goodsCopy);
                var originalNewPictureIdentifiers = new Dictionary<int, int>();
                if (copyImages)
                {
                    var goodsPictures = _goodsService.GetGoodsPicturesByGoodsId(goods.Id);
                    foreach (var goodsPicture in goodsPictures)
                    {
                        var picture = _pictureService.GetPictureById(goodsPicture.PictureId);
                        var pictureCopy = _pictureService.InsertPicture(
                            _pictureService.LoadPictureBinary(picture),
                            picture.MimeType,
                            null,
                            true);
                        _goodsService.InsertGoodsPicture(new GoodsPicture()
                        {
                            GoodsId = goodsCopy.Id,
                            PictureId = pictureCopy.Id,
                            DisplayOrder = goodsPicture.DisplayOrder
                        });
                        originalNewPictureIdentifiers.Add(picture.Id, pictureCopy.Id);
                    }
                }
                var psa = _goodsParameterService.GetGoodsParameterMappingByGoodsId(goods.Id);
                foreach (var goodsParameterMapping in psa)
                {
                    var psaCopy = new GoodsParameterMapping()
                    {
                        GoodsId = goodsCopy.Id,
                        GoodsParameterOptionId = goodsParameterMapping.GoodsParameterOptionId,
                        AllowFiltering = goodsParameterMapping.AllowFiltering,
                        DisplayOrder = goodsParameterMapping.DisplayOrder
                    };
                    _goodsParameterService.InsertGoodsParameterMapping(psaCopy);
                }


                var associatedAttributes = new Dictionary<int, int>();
                var associatedAttributeValues = new Dictionary<int, int>();
                foreach (var pattr in _goodsSpecService.GetGoodsSpecMappingByGoodsId(goods.Id))
                {
                    var pattrCopy = new GoodsSpecMapping()
                    {
                        GoodsId = goodsCopy.Id,
                        GoodsSpecId = pattr.GoodsSpecId,
                        GoodsSpecName=pattr.GoodsSpecName,
                    };
                    _goodsSpecService.InsertGoodsSpecMapping(pattrCopy);
                    associatedAttributes.Add(pattr.Id, pattrCopy.Id);

                    var goodsSpecValues = _goodsSpecService.GetGoodsSpecValues(pattr.GoodsSpecId);
                    foreach (var goodsSpecValue in goodsSpecValues)
                    {
                        var pvavCopy = new GoodsSpecValue()
                        {
                            GoodsSpecId = pattrCopy.Id,
                            Name = goodsSpecValue.Name
                        };
                        _goodsSpecService.InsertGoodsSpecValue(pvavCopy);

                        associatedAttributeValues.Add(goodsSpecValue.Id, pvavCopy.Id);
                    }
                }
                foreach (var combination in _goodsSpecService.GetAllGoodsSpecCombinations(goods.Id))
                {
                    string newAttributesXml = "";
                    var parsedGoodsSpecMappings = _goodsSpecParser.ParseGoodsSpecs(combination.AttributesXml);
                    foreach (var mapping in parsedGoodsSpecMappings)
                    {
                        if (associatedAttributes.ContainsKey(mapping.Id))
                        {
                            int newPvaId = associatedAttributes[mapping.Id];
                            var newPva = _goodsSpecService.GetGoodsSpecMappingById(newPvaId);
                            if (newPva != null)
                            {
                                var oldPvaValuesStr = _goodsSpecParser.ParseValues(combination.AttributesXml, mapping.Id);
                                foreach (var oldPvaValueStr in oldPvaValuesStr)
                                {
                                    int oldPvaValue = int.Parse(oldPvaValueStr);
                                    if (associatedAttributeValues.ContainsKey(oldPvaValue))
                                    {
                                        int newPvavId = associatedAttributeValues[oldPvaValue];
                                        var newPvav = _goodsSpecService.GetGoodsSpecValueById(newPvavId);
                                        if (newPvav != null)
                                        {
                                            newAttributesXml = _goodsSpecParser.AddGoodsSpec(newAttributesXml,
                                                newPva, newPvav.Id.ToString());
                                        }
                                    }
                                }
                            }
                        }
                    }
                    var combinationCopy = new GoodsSpecCombination()
                    {
                        GoodsId = goodsCopy.Id,
                        AttributesXml = newAttributesXml,
                        StockQuantity = combination.StockQuantity,
                        AllowOutOfStockOrders = combination.AllowOutOfStockOrders,
                        Sku = combination.Sku
                    };
                    _goodsSpecService.InsertGoodsSpecCombination(combinationCopy);
                }

            }

            return goodsCopy;
        }

        #endregion
    }
}
